{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Expressions and Arithmetic" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" }, "tags": [ "remove-cell" ] }, "source": [ "**CS1302 Introduction to Computer Programming**\n", "___" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Operators" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The followings are common operators you can use to form an expression in Python:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "| Operator | Operation | Example |\n", "| --------: | :------------- | :-----: |\n", "| unary `-` | Negation | `-y` |\n", "| `+` | Addition | `x + y` |\n", "| `-` | Subtraction | `x - y` |\n", "| `*` | Multiplication | `x*y` |\n", "| `/` | Division | `x/y` |" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- `x` and `y` in the examples are called the *left and right operands* respectively.\n", "- The first operator is a *unary operator*, which operates on just one operand. \n", " (`+` can also be used as a unary operator, but that is not useful.)\n", "- All other operators are *binary operators*, which operate on two operands." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Python also supports some more operators such as the followings:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "| Operator | Operation | Example |\n", "| -------: | :--------------- | :-----: |\n", "| `//` | Integer division | `x//y` |\n", "| `%` | Modulo | `x%y` |\n", "| `**` | Exponentiation | `x**y` |" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T01:56:24.675900Z", "start_time": "2020-09-12T01:56:24.573989Z" }, "code_folding": [ 0 ], "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "629a3e54b5494fd69c53888dea1f3289", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(Text(value='10', description='operand1'), Dropdown(description='operator', options={'+':…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# ipywidgets to demonstrate the operations of binary operators\n", "from ipywidgets import interact\n", "\n", "binary_operators = {\n", " \"+\": \" + \",\n", " \"-\": \" - \",\n", " \"*\": \"*\",\n", " \"/\": \"/\",\n", " \"//\": \"//\",\n", " \"%\": \"%\",\n", " \"**\": \"**\",\n", "}\n", "\n", "\n", "@interact(operand1=r\"10\", operator=binary_operators, operand2=r\"3\")\n", "def binary_operation(operand1, operator, operand2):\n", " expression = f\"{operand1}{operator}{operand2}\"\n", " value = eval(expression)\n", " print(\n", " f\"\"\"{'Expression:':>11} {expression}\\n{'Value:':>11} {value}\\n{'Type:':>11} {type(value)}\"\"\"\n", " )" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** What is the difference between `/` and `//`?" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "integer-division", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "- `/` is the usual division, and so `10/3` returns the floating-point number $3.\\dot{3}$.\n", "- `//` is integer division, and so `10//3` gives the integer quotient 3." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**What does the modulo operator `%` do?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "You can think of it as computing the remainder, but the [truth](https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations) is more complicated than required for the course." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "**Exercise** What does `'abc' * 3` mean? What about `10 * 'a'`?" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "concatenation", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "- The first expression means concatenating `'abc'` three times.\n", "- The second means concatenating `'a'` ten times." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Exercise** How can you change the default operands (`10` and `3`) for different operators so that the overall expression has type `float`. \n", "Do you need to change all the operands to `float`?" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "mixed-type", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "- `/` already returns a `float`.\n", "- For all other operators, changing at least one of the operands to `float` will return a `float`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Operator Precedence and Associativity" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "An expression can consist of a sequence of operations performed in a row such as `x + y*z`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "**How to determine which operation should be performed first?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Like arithmetics, the order of operations is decided based on the following rules applied sequentially: \n", "1. *Grouping* by parentheses: inner grouping first\n", "1. Operator *precedence/priority*: higher precedence first\n", "1. Operator *associativity*: \n", " - Left associativity: Associate all operations on the left as the left operand, e.g., \n", " `2 + 3 + 4 + 5` is equivalent to `((2 + 3) + 4) + 5`\n", " - Right associativity: Associate all operations on the right as the right operand, e.g., \n", " `2 ** 3 ** 4` is equivalent to `2 ** (3 ** (4 ** 5))`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**What are the operator precedence and associativity?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The following table gives a concise summary:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "| Operators | Associativity |\n", "| :--------------- | :-----------: |\n", "| `**` | right |\n", "| `-` (unary) | right |\n", "| `*`,`/`,`//`,`%` | left |\n", "| `+`,`-` | left |" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Play with the following widget to understand the precedence and associativity of different operators. \n", "In particular, explain whether the expression `-10 ** 2*3` gives $(-10)^{2\\times 3}= 10^6 = 1000000$." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:41:21.545421Z", "start_time": "2020-09-12T02:41:21.484702Z" }, "code_folding": [ 0 ], "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "7f157497667644f9a1f9ed830005b94f", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(Dropdown(description='operator1', options={'None': '', 'unary -': '-'}, value=''), Dropd…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# demonstrate operator precedence\n", "from ipywidgets import fixed\n", "\n", "\n", "@interact(\n", " operator1={\"None\": \"\", \"unary -\": \"-\"},\n", " operand1=fixed(r\"10\"),\n", " operator2=binary_operators,\n", " operand2=fixed(r\"2\"),\n", " operator3=binary_operators,\n", " operand3=fixed(r\"3\"),\n", ")\n", "def three_operators(operator1, operand1, operator2, operand2, operator3, operand3):\n", " expression = f\"{operator1}{operand1}{operator2}{operand2}{operator3}{operand3}\"\n", " value = eval(expression)\n", " print(\n", " f\"\"\"{'Expression:':>11} {expression}\\n{'Value:':>11} {value}\\n{'Type:':>11} {type(value)}\"\"\"\n", " )" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "precedence", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "The expression evaluates to $(-(10^2))\\times 3=-300$ instead because the exponentiation operator `**` has higher precedence than both the multiplication `*` and the negation operators `-`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Exercise** To avoid confusion in the order of operations, we should follow the [style guide](https://www.python.org/dev/peps/pep-0008/#other-recommendations) when writing expression. \n", "What is the proper way to write `-10 ** 2*3`? " ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:42:06.838771Z", "start_time": "2020-09-12T02:42:06.821964Z" }, "nbgrader": { "grade": true, "grade_id": "pep8", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-300\n", "300\n" ] } ], "source": [ "print(-10**2 * 3) # can use code-prettify or formatter to fix incorrect styles\n", "print((-10)**2 * 3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Augmented Assignment Operators" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- For convenience, Python defines the [augmented assignment operators](https://docs.python.org/3/reference/simple_stmts.html#grammar-token-augmented-assignment-stmt) such as `+=`, where \n", "- `x += 1` means `x = x + 1`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The following widgets demonstrate other augmented assignment operators." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:50:22.431213Z", "start_time": "2020-09-12T02:50:22.389022Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "99c266d192b0403aa14676c6d78717fd", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(Dropdown(description='operator', options=('+=', '-=', '*=', '/=', '//=', '%=', '**='), v…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from ipywidgets import fixed, interact\n", "\n", "\n", "@interact(\n", " initial_value=fixed(r\"10\"),\n", " operator=[\"+=\", \"-=\", \"*=\", \"/=\", \"//=\", \"%=\", \"**=\"],\n", " operand=fixed(r\"2\"),\n", ")\n", "def binary_operation(initial_value, operator, operand):\n", " assignment = f\"x = {initial_value}\\nx {operator} {operand}\"\n", " _locals = {}\n", " exec(assignment, None, _locals)\n", " print(f\"Assignments:\\n{assignment:>10}\\nx: {_locals['x']} ({type(_locals['x'])})\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Can we create an expression using (augmented) assignment operators? Try running the code to see the effect." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-09-04T12:31:45.339984Z", "start_time": "2020-09-04T12:31:45.335881Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "ename": "SyntaxError", "evalue": "invalid syntax (, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m 3*(x = 15)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], "source": [ "3*(x = 15)" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "assignment-statement", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "Assignment operators are used in assignment statements, which are not expressions because they cannot be evaluated." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "Starting Python 3.8, there is an [assignment expression](https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions) using the operator `:=`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(15, 45)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y = 3*(x := 15)\n", "x, y" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "rise": { "enable_chalkboard": true, "scroll": true, "theme": "white" }, "toc": { "base_numbering": 1, "nav_menu": { "height": "195px", "width": "330px" }, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "454.418px", "left": "1533px", "top": "110.284px", "width": "435.327px" }, "toc_section_display": true, "toc_window_display": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }